home *** CD-ROM | disk | FTP | other *** search
- /*
- * $Id: texture.c,v 1.1.1.1 2000/04/07 19:44:51 tfrieden Exp $
- *
- * $Date: 2000/04/07 19:44:51 $
- * $Revision: 1.1.1.1 $
- *
- * (C) 1999 by Hyperion
- * All rights reserved
- *
- * This file is part of the MiniGL library project
- * See the file Licence.txt for more details
- *
- */
-
- #include "sysinc.h"
- #include <stdlib.h>
- #include <stdio.h>
-
- static char rcsid[] = "$Id: texture.c,v 1.1.1.1 2000/04/07 19:44:51 tfrieden Exp $";
-
-
- #ifndef __PPC__
- extern struct ExecBase *SysBase;
- #endif
-
- void tex_FreeTextures(GLcontext context);
- void tex_SetEnv(GLcontext context, GLenum env);
- ULONG tex_GLFilter2W3D(GLenum filter);
- void tex_SetFilter(GLcontext context, GLenum min, GLenum mag);
- void tex_SetWrap(GLcontext context, GLenum wrap_s, GLenum wrap_t);
- void RGBA_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
- void RGBA_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
- void RGB_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
- void RGB_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height);
- ULONG MGLConvert(GLcontext context, const GLvoid *inputp, UWORD *output, int width, int height, GLenum internalformat, GLenum format);
-
- static ULONG Allocated_Size = 0;
- static ULONG Peak_Size = 0;
-
- void *tex_Alloc(ULONG size)
- {
- ULONG *x;
- Allocated_Size += size+4;
- x=(ULONG *)malloc(size+4);
- *x = size;
-
- if (Allocated_Size > Peak_Size) Peak_Size = Allocated_Size;
-
- return x+1;
- }
-
- void tex_Free(void *chunk)
- {
- ULONG *mem = (ULONG *)chunk;
- mem--;
- Allocated_Size -= *mem;
- Allocated_Size -= 4;
- free(mem);
- }
-
- void tex_Statistic(void)
- {
- printf("Peak Allocation Size: %ld\n", Peak_Size);
- }
-
- void MGLTexMemStat(GLcontext context, GLint *Current, GLint *Peak)
- {
- if (Current) *Current = (GLint)Allocated_Size;
- if (Peak) *Peak = (GLint)Peak_Size;
- }
-
- void GLDeleteTextures(GLcontext context, GLsizei n, const GLuint *textures)
- {
- int i;
- for (i=0; i<n; i++)
- {
- int j = *textures++;
- if (context->w3dTexBuffer[j])
- {
- W3D_FreeTexObj(context->w3dContext, context->w3dTexBuffer[j]);
- context->w3dTexBuffer[j] = NULL;
- }
- if (context->w3dTexMemory[j])
- {
- void *x = context->w3dTexMemory[j];
- tex_Free(x);
- context->w3dTexMemory[j] = NULL;
- }
- }
- }
-
- void GLGenTextures(GLcontext context, GLsizei n, GLuint *textures)
- {
- int i,j;
-
- j = 1;
- for (i=0; i<n; i++)
- {
- while (j < context->TexBufferSize)
- {
- if (context->w3dTexBuffer[j] == NULL) break;
- j++;
- }
- GLFlagError(context, j == context->TexBufferSize, GL_INVALID_OPERATION);
- *textures = j;
- textures++;
- }
- }
-
-
- void tex_FreeTextures(GLcontext context)
- {
- int i;
-
- for (i=0; i<context->TexBufferSize; i++)
- {
- if (context->w3dTexBuffer[i])
- {
- W3D_FreeTexObj(context->w3dContext, context->w3dTexBuffer[i]);
- }
-
- if (context->w3dTexMemory[i])
- {
- tex_Free(context->w3dTexMemory[i]);
- }
-
- context->w3dTexBuffer[i] = 0;
- context->w3dTexMemory[i] = 0;
- }
- W3D_FreeAllTexObj(context->w3dContext);
- }
-
- void tex_SetEnv(GLcontext context, GLenum env)
- {
- W3D_Texture *tex = context->w3dTexBuffer[context->CurrentBinding];
- if (!tex) return;
-
- switch(env)
- {
- case GL_MODULATE: W3D_SetTexEnv(context->w3dContext, tex, W3D_MODULATE, NULL);
- break;
- case GL_DECAL: W3D_SetTexEnv(context->w3dContext, tex, W3D_DECAL, NULL);
- break;
- case GL_REPLACE: W3D_SetTexEnv(context->w3dContext, tex, W3D_REPLACE, NULL);
- break;
- default: break;
- }
- }
-
- ULONG tex_GLFilter2W3D(GLenum filter)
- {
- switch(filter)
- {
- case GL_NEAREST: return W3D_NEAREST;
- case GL_LINEAR: return W3D_LINEAR;
- case GL_NEAREST_MIPMAP_NEAREST: return W3D_NEAREST_MIP_NEAREST;
- case GL_LINEAR_MIPMAP_NEAREST: return W3D_LINEAR_MIP_NEAREST;
- case GL_NEAREST_MIPMAP_LINEAR: return W3D_NEAREST_MIP_LINEAR;
- case GL_LINEAR_MIPMAP_LINEAR: return W3D_LINEAR_MIP_LINEAR;
- }
- return 0;
- }
-
- void tex_SetFilter(GLcontext context, GLenum min, GLenum mag)
- {
- ULONG minf, magf;
-
- W3D_Texture *tex = context->w3dTexBuffer[context->CurrentBinding];
- if (!tex) return;
-
- minf = tex_GLFilter2W3D(min);
- magf = tex_GLFilter2W3D(mag);
-
- W3D_SetFilter(context->w3dContext, tex, minf, magf);
- }
-
- void tex_SetWrap(GLcontext context, GLenum wrap_s, GLenum wrap_t)
- {
- ULONG Ws,Wt;
- W3D_Texture *tex = context->w3dTexBuffer[context->CurrentBinding];
- if (!tex) return;
-
- if (wrap_s == GL_REPEAT) Ws = W3D_REPEAT;
- else Ws = W3D_CLAMP;
- if (wrap_t == GL_REPEAT) Wt = W3D_REPEAT;
- else Wt = W3D_CLAMP;
-
- W3D_SetWrapMode(context->w3dContext, tex, Ws, Wt, NULL);
- }
-
- void GLTexEnvi(GLcontext context, GLenum target, GLenum pname, GLint param)
- {
- //LOG(2, glTexEnvi, "%d %d", pname, param);
- tex_SetEnv(context, param);
- context->TexEnv = (GLenum)param;
- }
-
- void GLTexParameteri(GLcontext context, GLenum target, GLenum pname, GLint param)
- {
- GLenum min, mag;
- GLenum wraps, wrapt;
- //LOG(2, glTexParameteri, "%d %d %d", target, pname, param);
- switch(pname)
- {
- case GL_TEXTURE_MIN_FILTER:
- mag = context->MagFilter;
- tex_SetFilter(context, mag, (GLenum)param);
- context->MinFilter = (GLenum)param;
- break;
- case GL_TEXTURE_MAG_FILTER:
- min = context->MinFilter;
- tex_SetFilter(context, (GLenum)param, min);
- context->MagFilter = (GLenum)param;
- break;
- case GL_TEXTURE_WRAP_S:
- wrapt = context->WrapT;
- tex_SetWrap(context, (GLenum)param, wrapt);
- context->WrapS = (GLenum)param;
- break;
- case GL_TEXTURE_WRAP_T:
- wraps = context->WrapS;
- tex_SetWrap(context, wraps, (GLenum)param);
- context->WrapT = (GLenum)param;
- break;
- default:
- GLFlagError(context, 1, GL_INVALID_ENUM);
- }
- }
-
- void GLPixelStorei(GLcontext context, GLenum pname, GLint param)
- {
- switch(pname)
- {
- case GL_PACK_ALIGNMENT:
- context->PackAlign = param;
- break;
- case GL_UNPACK_ALIGNMENT:
- context->UnpackAlign = param;
- break;
- default:
- // Others here
- break;
- }
- }
-
- void GLBindTexture(GLcontext context, GLenum target, GLuint texture)
- {
- //LOG(2, glBindTexture, "%d %d", target, texture);
- GLFlagError(context, target != GL_TEXTURE_2D, GL_INVALID_ENUM);
- context->CurrentBinding = texture;
- if (context->w3dTexBuffer[context->CurrentBinding] == NULL)
- { // Set to default for unbound objects
- context->TexEnv = GL_MODULATE;
- context->MinFilter = GL_NEAREST;
- context->MagFilter = GL_NEAREST;
- context->WrapS = GL_REPEAT;
- context->WrapT = GL_REPEAT;
- }
- }
-
- /*
- ** There are two possible output formats:
- ** - RGB
- ** - RGBA
- **
- ** There are two possible input formats:
- ** - RGB
- ** - RGBA
- **
- ** Thus there must be four conversion routines, since the
- ** routine must be able to add or remove the alpha component
- **
- ** The following set of routines assumes that input is always given as
- ** a stream of GL_UNSIGNED_BYTE with either three or four components.
- **
- ** ROOM FOR IMPROVMENT
- ** These routines assume way too much to be considered anything else but
- ** special cases. The whole texture stuff should be reworked to include
- ** possible convertion routines for all kinds of textures. This could, of
- ** course, be left to Warp3D, but this would mean there has to be two sets
- ** of textures in memory, which is clearly too much. Perhaps we should
- ** change the behaviour of Warp3D in this point - room for discussion.
- */
-
- #define CORRECT_ALIGN \
- if ((int)input % context->PackAlign) \
- { \
- input += context->PackAlign - ((int)input % context->PackAlign);\
- } \
-
- #define ARGBFORM(a,r,g,b) \
- (UWORD)(((( a & 0xf0 ) << 8) \
- |(( r & 0xf0 ) << 4) \
- |(( g & 0xf0 ) ) \
- |(( b & 0xf0 ) >> 4)))
-
- #define RGBFORM(r,g,b) \
- (UWORD)(0x8000 | ((r & 0xF8) << 7) \
- | ((g & 0xF8) << 2) \
- | ((b & 0xF8) >> 3))
-
-
- #define REDBYTE(rgb) (((UWORD)rgb & 0x7C00) >> 7)
- #define GREENBYTE(rgb) (((UWORD)rgb & 0x03E0) >> 2)
- #define BLUEBYTE(rgb) (((UWORD)rgb & 0x001F) << 3)
- #define RGB_GET(i) ((UBYTE *)(context->PaletteData)+3*i)
- #define ARGB_GET(i) ((UBYTE *)(context->PaletteData)+4*i)
-
- /*
- ** This function converts a non-alpha texture buffer into a
- ** alpha'ed texture buffer. This is used in case additive blending
- ** was selected but the texture does not have alpha, and additive blending
- ** is not
- */
- void tex_AddAlpha(UWORD *output, int width, int height)
- {
- int size = width*height;
- int r,g,b,a;
- UWORD x;
-
- while (size)
- {
- x=*output;
-
- r = REDBYTE(x);
- g = GREENBYTE(x);
- b = BLUEBYTE(x);
-
- /*a=(r+g+b)/3;*/
- a=(r>g)?r:g;
- a=(a>b)?a:b;
-
- // These should emulate additive blending, so ensure it's in some appropriate range
- /*/ if (a > 240)
- {
- a = 240;
- }*/
-
- a *= 0.8;
-
- *output = ARGBFORM(a,r,g,b);
-
- output++; size--;
- }
- }
-
-
- /*
- ** Convert the currently bound texture to a format that has an alpha channel.
- ** Also sets the texture parameters according to the current settings.
- */
- void tex_ConvertTexture(GLcontext context)
- {
- W3D_Texture *newtex;
- W3D_Texture *oldtex = context->w3dTexBuffer[context->CurrentBinding];
- UWORD *output = (UWORD *)context->w3dTexMemory[context->CurrentBinding];
- struct TagItem AllocTags[20];
-
- if (!oldtex) return;
- if (oldtex->texfmtsrc == context->w3dAlphaFormat) return;
-
- tex_AddAlpha(output, oldtex->texwidth, oldtex->texheight);
- AllocTags[0].ti_Tag = W3D_ATO_IMAGE;
- AllocTags[0].ti_Data = (ULONG)context->w3dTexMemory[context->CurrentBinding];
-
- AllocTags[1].ti_Tag = W3D_ATO_FORMAT;
- AllocTags[1].ti_Data = context->w3dAlphaFormat;
-
- AllocTags[2].ti_Tag = W3D_ATO_WIDTH;
- AllocTags[2].ti_Data = oldtex->texwidth;
-
- AllocTags[3].ti_Tag = W3D_ATO_HEIGHT;
- AllocTags[3].ti_Data = oldtex->texheight;
-
- AllocTags[4].ti_Tag = TAG_DONE;
- AllocTags[4].ti_Data = 0;
-
- newtex = W3D_AllocTexObj(context->w3dContext, NULL, AllocTags);
- if (!newtex) return;
-
- W3D_FreeTexObj(context->w3dContext, oldtex);
- context->w3dTexBuffer[context->CurrentBinding] = newtex;
-
- tex_SetEnv(context, context->TexEnv);
- tex_SetFilter(context, context->MinFilter, context->MagFilter);
- tex_SetWrap(context, context->WrapS, context->WrapT);
- }
-
- void RGBA_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
- {
- int i,j;
- UBYTE r,g,b,a;
- for (i=0; i<height;i++)
- {
- for (j=0; j<width; j++)
- {
- r=*input++;
- g=*input++;
- b=*input++;
- a=*input++;
- *output++ = RGBFORM(r,g,b);
- CORRECT_ALIGN
- }
- }
- }
-
- void RGBA_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
- {
- int i,j;
- UBYTE r,g,b,a;
- for (i=0; i<height;i++)
- {
- for (j=0; j<width; j++)
- {
- r=*input++;
- g=*input++;
- b=*input++;
- a=*input++;
- *output++ = ARGBFORM(a,r,g,b);
- CORRECT_ALIGN
- }
- }
- }
-
- void RGB_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
- {
- int i,j;
- UBYTE r,g,b;
- for (i=0; i<height;i++)
- {
- for (j=0; j<width; j++)
- {
- r=*input++;
- g=*input++;
- b=*input++;
- *output++ = RGBFORM(r,g,b);
- CORRECT_ALIGN
- }
- }
- }
-
- void RGB_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
- {
- int i,j;
- UBYTE r,g,b;
- for (i=0; i<height;i++)
- {
- for (j=0; j<width; j++)
- {
- r=*input++;
- g=*input++;
- b=*input++;
- *output++ = ARGBFORM(255,r,g,b);
- CORRECT_ALIGN
- }
- }
- }
-
- void INDEX_RGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
- {
- int i,j;
- UBYTE ind;
- UBYTE r,g,b;
-
- if (context->PaletteFormat == GL_RGB)
- {
- for (i=0; i<height; i++)
- {
- for (j=0; j<width; j++)
- {
- ind = *input++;
- r = *RGB_GET(ind);
- g = *(RGB_GET(ind)+1);
- b = *(RGB_GET(ind)+2);
- *output++ = RGBFORM(r,g,b);
- CORRECT_ALIGN
- }
- }
- }
- else
- {
- for (i=0; i<height; i++)
- {
- for (j=0; j<width; j++)
- {
- ind = *input++;
- r = *RGB_GET(ind);
- g = *(ARGB_GET(ind)+1);
- b = *(ARGB_GET(ind)+2);
- *output++ = RGBFORM(r,g,b);
- CORRECT_ALIGN
- }
- }
-
- }
- }
-
- void INDEX_ARGB(GLcontext context, GLubyte *input, UWORD *output, int width, int height)
- {
- int i,j;
- UBYTE ind;
- UBYTE r,g,b,a;
-
- if (context->PaletteFormat == GL_RGB)
- {
- for (i=0; i<height; i++)
- {
- for (j=0; j<width; j++)
- {
- ind = *input++;
- r = *RGB_GET(ind);
- g = *(RGB_GET(ind)+1);
- b = *(RGB_GET(ind)+2);
- *output++ = ARGBFORM(255,r,g,b);
- CORRECT_ALIGN
- }
- }
- }
- else
- {
- for (i=0; i<height; i++)
- {
- for (j=0; j<width; j++)
- {
- ind = *input++;
- r = *RGB_GET(ind);
- g = *(ARGB_GET(ind)+1);
- b = *(ARGB_GET(ind)+2);
- a = *(ARGB_GET(ind)+3);
- *output++ = ARGBFORM(a,r,g,b);
- CORRECT_ALIGN
- }
- }
-
- }
- }
-
- void L8_L8(GLcontext context, GLubyte *input, GLubyte *output, int width, int height)
- {
- int i,j;
-
- for (i=0; i<height;i++)
- {
- for (j=0; j<width; j++) {
- *output++ = *input++;
- }
- }
- }
-
- ULONG MGLConvert(GLcontext context, const GLvoid *inputp, UWORD *output, int width, int height, GLenum internalformat, GLenum format)
- {
- GLvoid *input = (GLvoid *)inputp;
-
- switch(internalformat) // The format the texture should have
- {
- case GL_LUMINANCE:
- switch(format) // the format of the pixel (input) data
- {
- case GL_LUMINANCE:
- L8_L8(context, (GLubyte *)input, (GLubyte *)output, width, height);
- return W3D_L8;
- }
- break;
-
- case 3:
- case GL_RGB:
- switch(format) // the format of the pixel (input) data
- {
- case GL_RGB:
- RGB_RGB(context, (GLubyte *)input, output, width, height);
- return context->w3dFormat;
- case GL_RGBA:
- RGBA_RGB(context, (GLubyte *)input, output, width, height);
- return context->w3dFormat;
- case GL_COLOR_INDEX:
- INDEX_RGB(context, (GLubyte *)input, output, width, height);
- return context->w3dFormat;
- }
- break;
-
- case 4:
- case GL_RGBA:
- switch(format) // format of the pixel (input) data
- {
- case GL_RGB:
- RGB_ARGB(context, (GLubyte *)input, output, width, height);
- return context->w3dAlphaFormat;
- case GL_RGBA:
- RGBA_ARGB(context, (GLubyte *)input, output, width, height);
- return context->w3dAlphaFormat;
- case GL_COLOR_INDEX:
- INDEX_ARGB(context, (GLubyte *)input, output, width, height);
- return context->w3dAlphaFormat;
- }
- break;
- }
- }
-
- void GLTexImage2DNoMIP(GLcontext context, GLenum gltarget, GLint level,
- GLint internalformat, GLsizei width, GLsizei height, GLint border,
- GLenum format, GLenum type, const GLvoid *pixels);
-
-
- void GLTexImage2D(GLcontext context, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
- {
- int current = context->CurrentBinding;
- ULONG w,h;
- ULONG targetsize;
- ULONG error;
- UBYTE *target;
- int i,iw,ih;
- void *miparray[16];
- ULONG useFormat;
-
- struct TagItem AllocTags[20];
-
- if (context->NoMipMapping == GL_TRUE)
- {
- GLTexImage2DNoMIP(context, gltarget, level, internalformat, width,
- height, border, format, type, pixels);
- return;
- }
-
- //LOG(3, glTexImage2D, "target = %d level=%d, size=%d×%d", gltarget, level, width, height);
- GLFlagError(context, type != GL_UNSIGNED_BYTE, GL_INVALID_OPERATION);
- GLFlagError(context, gltarget != GL_TEXTURE_2D, GL_INVALID_ENUM);
-
- /*
- ** We will use width and height only when the mipmap level
- ** is really 0. Otherwise, we need to upscale the values
- ** according to the level.
- **
- ** Note this will most likely be difficult with non-square
- ** textures, as the first side to reach one will remain
- ** there. For example, consider the sequence
- ** 8x4, 4x2, 2x1, 1x1
- ** 0 1 2 3
- ** If the 1x1 mipmap is given, upscaling will yield 8x8, not 8x4
- */
-
- w=(ULONG)width;
- h=(ULONG)height;
- if (level)
- {
- int i=level;
- while (i)
- {
- w*=2; h*=2; i--;
- }
- }
-
- if (context->w3dTexBuffer[current] == NULL)
- {
- /*
- ** Create a new texture object
- ** Get the memory
- */
-
- targetsize = (w * h * context->w3dBytesPerTexel * 4) / 3;
- if (context->w3dTexMemory[current])
- tex_Free(context->w3dTexMemory[current]);
- context->w3dTexMemory[current] = (GLubyte *)tex_Alloc(targetsize);
- if (!context->w3dTexMemory[current])
- return;
- }
-
- /*
- ** Find the starting address for the given mipmap level in the
- ** texture memory area
- */
-
- target = context->w3dTexMemory[current];
- i = level;
- iw = w; ih=h;
- while (i)
- {
- target += iw * ih * context->w3dBytesPerTexel;
- i -- ;
- if (iw>1) iw/=2;
- if (ih>1) ih/=2;
- }
-
- /*
- ** Convert the data to the target address
- */
- useFormat = MGLConvert(context, pixels, (UWORD *)target, width, height, internalformat, format);
-
- /*
- ** Create a new W3D_Texture if none was present, using the converted
- ** data.
- ** Otherwise, call W3D_UpdateTexImage
- */
-
- if (context->w3dTexBuffer[current] == NULL)
- {
- i=0;
- iw=w;
- ih=h;
- target = context->w3dTexMemory[current];
- while (1)
- {
- miparray[i++] = target;
- if (iw == 1 && ih == 1) break;
-
- target += iw * ih * context->w3dBytesPerTexel;
- if (iw > 1) iw /= 2;
- if (ih > 1) ih /= 2;
- }
-
- AllocTags[0].ti_Tag = W3D_ATO_IMAGE;
- AllocTags[0].ti_Data = (ULONG)context->w3dTexMemory[current];
-
- AllocTags[1].ti_Tag = W3D_ATO_FORMAT;
- AllocTags[1].ti_Data = useFormat;
-
- AllocTags[2].ti_Tag = W3D_ATO_WIDTH;
- AllocTags[2].ti_Data = w;
-
- AllocTags[3].ti_Tag = W3D_ATO_HEIGHT;
- AllocTags[3].ti_Data = h;
-
- AllocTags[4].ti_Tag = W3D_ATO_MIPMAP;
- AllocTags[4].ti_Data = 0;
-
- AllocTags[5].ti_Tag = W3D_ATO_MIPMAPPTRS;
- AllocTags[5].ti_Data = (ULONG)miparray;
-
- AllocTags[6].ti_Tag = TAG_DONE;
- AllocTags[6].ti_Data = 0;
-
- context->w3dTexBuffer[current] = W3D_AllocTexObj(context->w3dContext, &error, AllocTags);
-
- if (context->w3dTexBuffer[current] == NULL || error != W3D_SUCCESS) return;
-
- /*
- ** Set the appropriate wrap modes, texture env, and filters
- */
- tex_SetWrap(context, context->WrapS, context->WrapT);
- tex_SetFilter(context, context->MinFilter, context->MagFilter);
- tex_SetEnv(context, context->TexEnv);
-
- }
- else
- {
- W3D_UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
- target, level, NULL);
- }
- }
-
- void GLTexImage2DNoMIP(GLcontext context, GLenum gltarget, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
- {
- int current = context->CurrentBinding;
- ULONG w,h;
- ULONG targetsize;
- ULONG error;
- UBYTE *target;
- ULONG useFormat;
- static struct TagItem AllocTags[20];
-
- //LOG(3, glTexImage2DNoMIP, "target = %d level=%d, size=%d×%d", gltarget, level, width, height);
- GLFlagError(context, type != GL_UNSIGNED_BYTE, GL_INVALID_OPERATION);
- GLFlagError(context, gltarget != GL_TEXTURE_2D, GL_INVALID_ENUM);
-
- if (level != 0) return;
-
- w=(ULONG)width;
- h=(ULONG)height;
-
- if (context->w3dTexBuffer[current] == NULL)
- {
- /*
- ** Create a new texture object
- ** Get the memory
- */
-
- targetsize = (w * h * context->w3dBytesPerTexel);
- if (context->w3dTexMemory[current])
- tex_Free(context->w3dTexMemory[current]);
- context->w3dTexMemory[current] = (GLubyte *)tex_Alloc(targetsize);
- if (!context->w3dTexMemory[current])
- return;
- }
-
- target = context->w3dTexMemory[current];
-
- /*
- ** Convert the data to the target address
- */
- useFormat = MGLConvert(context, pixels, (UWORD *)target, width, height, internalformat, format);
-
- /*
- ** Create a new W3D_Texture if none was present, using the converted
- ** data.
- ** Otherwise, call W3D_UpdateTexImage
- */
-
- if (context->w3dTexBuffer[current] == NULL)
- {
- W3D_Texture *tex;
-
- AllocTags[0].ti_Tag = W3D_ATO_IMAGE;
- AllocTags[0].ti_Data = (ULONG)context->w3dTexMemory[current];
-
- AllocTags[1].ti_Tag = W3D_ATO_FORMAT;
- AllocTags[1].ti_Data = useFormat;
-
- AllocTags[2].ti_Tag = W3D_ATO_WIDTH;
- AllocTags[2].ti_Data = w;
-
- AllocTags[3].ti_Tag = W3D_ATO_HEIGHT;
- AllocTags[3].ti_Data = h;
-
- AllocTags[4].ti_Tag = TAG_DONE;
- AllocTags[4].ti_Data = 0;
-
- tex = W3D_AllocTexObj(context->w3dContext, &error, AllocTags);
-
- if (tex == NULL || error != W3D_SUCCESS) return;
-
- context->w3dTexBuffer[current] = tex;
-
- /*
- ** Set the appropriate wrap modes, texture env, and filters
- */
- tex_SetWrap(context, context->WrapS, context->WrapT);
- tex_SetFilter(context, context->MinFilter, context->MagFilter);
- tex_SetEnv(context, context->TexEnv);
-
- }
- else
- {
- W3D_UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
- context->w3dTexMemory[current], 0, NULL);
- }
- }
-
- inline void tex_UpdateScanlineAlpha(UWORD *start, UBYTE *pixels, int numpixels)
- {
- int i;
- UBYTE r,g,b,a;
- for (i=0; i<numpixels; i++)
- {
- r=*pixels++;
- g=*pixels++;
- b=*pixels++;
- a=*pixels++;
-
- *start = ARGBFORM(a,r,g,b);
- start++;
- }
- }
-
- inline void tex_UpdateScanlineNoAlpha(UWORD *start, UBYTE *pixels, int numpixels)
- {
- int i;
- UBYTE r,g,b,a;
- for (i=0; i<numpixels; i++)
- {
- r=*pixels++;
- g=*pixels++;
- b=*pixels++;
- a=*pixels++;
-
- *start = RGBFORM(r,g,b);
- start++;
- }
- }
-
- inline void tex_UpdateScanlineVerbatim(UBYTE *start, UBYTE *pixels, int numpixels)
- {
- memcpy(pixels, start, numpixels);
- }
-
- void GLTexSubImage2DNoMIP(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
-
- void GLTexSubImage2D(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
- {
- int current = context->CurrentBinding;
-
- if (context->NoMipMapping == GL_TRUE)
- {
- GLTexSubImage2DNoMIP(context, target, level, xoffset, yoffset, width, height, format, type, (void *)pixels);
- return;
- }
-
- GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM);
- GLFlagError(context, context->w3dTexBuffer[current] == NULL, GL_INVALID_OPERATION);
-
- // GLFlagError(context, 1, GL_INVALID_OPERATION);
- }
-
- void GLTexSubImage2DNoMIP(GLcontext context, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
- {
- UBYTE *where;
- UBYTE *from = pixels;
- int current = context->CurrentBinding;
- int linelength;
- int sourcelength, sourceunit;
- int i;
-
-
- GLFlagError(context, target!=GL_TEXTURE_2D, GL_INVALID_ENUM);
- GLFlagError(context, context->w3dTexBuffer[context->CurrentBinding] == NULL, GL_INVALID_OPERATION);
- GLFlagError(context, type != GL_UNSIGNED_BYTE, GL_INVALID_ENUM);
-
- switch(format)
- {
- case GL_LUMINANCE:
- sourceunit = 1;
- break;
-
- case GL_RGBA:
- case 4:
- sourceunit = 4;
- break;
-
- case GL_RGB:
- case 3:
- sourceunit = 3;
- break;
- }
-
- linelength = context->w3dTexBuffer[current]->texwidth * context->w3dBytesPerTexel;
-
- sourcelength = width * sourceunit;
-
- where = (UBYTE *)context->w3dTexMemory[current]
- + linelength * yoffset
- + context->w3dBytesPerTexel * xoffset;
-
- if (context->w3dTexBuffer[current]->texfmtsrc == context->w3dFormat)
- {
- for (i=0; i<height; i++)
- {
- tex_UpdateScanlineNoAlpha((UWORD *)where, from, width);
- where += linelength;
- from += sourcelength;
- }
- }
- else if (context->w3dTexBuffer[current]->texfmtsrc == context->w3dAlphaFormat)
- {
- for (i=0; i<height; i++)
- {
- tex_UpdateScanlineAlpha((UWORD *)where, from, width);
- where += linelength;
- from += sourcelength;
- }
- }
- else
- {
- for (i=0; i<height; i++)
- {
- tex_UpdateScanlineVerbatim((UBYTE *)where, from, width*sourceunit);
- where += linelength;
- from += sourcelength;
- }
- }
-
- W3D_UpdateTexImage(context->w3dContext, context->w3dTexBuffer[current],
- context->w3dTexMemory[current], 0, NULL);
- }
-
- void GLTexGeni(GLcontext context, GLenum coord, GLenum mode, GLenum map)
- {
- // GLFlagError(context, 1, GL_INVALID_OPERATION);
- }
-
- void GLColorTable(GLcontext context, GLenum target, GLenum internalformat, GLint width, GLenum format, GLenum type, GLvoid *data)
- {
- int i;
- GLubyte *palette;
- GLubyte *where;
- GLubyte a,r,g,b;
-
- GLFlagError(context, width>256, GL_INVALID_VALUE);
- GLFlagError(context, target!=GL_COLOR_TABLE, GL_INVALID_OPERATION);
-
- palette = (GLubyte *)data;
- where = (GLubyte *)context->PaletteData;
-
- GLFlagError(context, where == NULL, GL_INVALID_OPERATION);
-
- switch(internalformat)
- {
- case 4:
- case GL_RGBA: // convert to argb from...
- switch(format)
- {
- case GL_RGB: // ...RGB, ignoring alpha
- for (i=0; i<width; i++)
- {
- r=*palette++;
- g=*palette++;
- b=*palette++;
- palette++;
- *where++ = r;
- *where++ = g;
- *where++ = b;
- }
- break;
- case GL_RGBA: // ...ARGB with alpha
- for (i=0; i<width; i++)
- {
- a=*palette++;
- r=*palette++;
- g=*palette++;
- b=*palette++;
- *where++ = a;
- *where++ = r;
- *where++ = g;
- *where++ = b;
- }
- break;
- }
- break;
- case 3:
- case GL_RGB: // convert to RGB from...
- switch(format)
- {
- case GL_RGB: // ...RGB without alpha
- for (i=0; i<width; i++)
- {
- r=*palette++;
- g=*palette++;
- b=*palette++;
- *where++ = r;
- *where++ = g;
- *where++ = b;
- }
- break;
- case GL_RGBA: // ...ARGB, assuming alpha == 1
- for (i=0; i<width; i++)
- {
- r=*palette++;
- g=*palette++;
- b=*palette++;
- *where++ = 255;
- *where++ = r;
- *where++ = g;
- *where++ = b;
- }
- break;
- }
- break;
- }
- context->PaletteFormat = format;
- context->PaletteSize = width;
- }
-